import { ProgressUI, ProgressUIEvent } from '../../ui/progress-ui';
import { TooltipUI } from '../../ui/tooltip-ui';
import { EventEmitter } from '../../common/event-emitter';
import { fromBytes } from '../../numbers/helpers';
import { ProgressElementInterface } from '../../ui/progress/ProgressElementInterface';
import { Progress, StateEvent } from './state-manager';

export enum UIControllerEvent {
  ProgressReset = 't1h0.ui.downloader.uiController.progress-reset',
  ProgressUpdate = 't1h0.ui.downloader.uiController.progress-update',
  ProgressComplete = 't1h0.ui.downloader.uiController.progress-complete',
}

/**
 * 下载UI控制器类
 * 负责管理下载过程中的所有UI交互和渲染逻辑
 */
export class DownloadUIController extends EventEmitter {
  /** 进度UI组件 */
  private __progressUI: ProgressUI;

  /** 工具提示UI组件 */
  private __tooltip: TooltipUI;

  /** 挂载目标元素 */
  private __target: HTMLElement;

  /**
   * 创建下载UI控制器实例
   * @param target - 挂载目标元素
   * @param progressElement - 自定义进度元素
   */
  constructor(target: HTMLElement, progressElement?: ProgressElementInterface) {
    super();
    this.__target = target;

    // 初始化UI组件
    this.__progressUI = new ProgressUI({
      target: this.__target,
      progressElement
    });

    // 初始化工具提示
    this.__tooltip = new TooltipUI({
      target: this.__target,
      content: {
        type: 'text',
        content: '单击开始下载，双击取消下载，下载过程中单击暂停/继续'
      }
    });

    this.__bindEvents();
  }

  /**
   * 绑定UI事件处理函数
   * 将DOM事件转换为业务事件供外部订阅
   * @private
   */
  private __bindEvents(): void {
    let clickTimeout: NodeJS.Timeout | null = null;
    // 双击事件 - 取消下载
    this.__progressUI.getElement().addEventListener('dblclick', (e) => {
      e.preventDefault();
      if (clickTimeout) {
        clearTimeout(clickTimeout);
        clickTimeout = null;
      }
      this.emit(StateEvent.DownloadCancel);
    });
    // 单击事件 - 开始/暂停下载
    this.__progressUI.getElement().addEventListener('click', () => {
      if (clickTimeout) {
        clearTimeout(clickTimeout);
      }
      clickTimeout = setTimeout(() => {
        this.emit(StateEvent.DownloadToggle);
      }, 300);
    });

    // 鼠标事件 - 工具提示显示/隐藏
    this.__progressUI.getElement().addEventListener('mouseenter', () => {
      this.__tooltip.show();
    });

    this.__progressUI.getElement().addEventListener('mouseleave', () => {
      this.__tooltip.hide();
    });

    this.on(UIControllerEvent.ProgressReset, () => {
      this.__progressUI.emit(ProgressUIEvent.Update, 0);
    })

    this.on(UIControllerEvent.ProgressUpdate, (progress: Progress) => {
      // 计算百分比(限制在0-100)
      const percent = Math.min(Math.round((progress.downloadedSize / progress.totalSize) * 100), 100);
      // 更新进度显示
      this.__updateProgress(percent, progress.downloadedSize, progress.totalSize, progress.speed);
    })
    this.on(UIControllerEvent.ProgressComplete, () => {
      this.__progressUI.emit(ProgressUIEvent.Update, 100);
    })
  }

  /**
   * 更新下载进度显示
   * @param percent - 下载百分比(0-100)
   * @param downloaded - 已下载字节数
   * @param total - 文件总字节数
   * @param speed - 下载速度(字节/秒)
   */
  private __updateProgress(percent: number, downloaded: number, total: number, speed: number): void {
    // 更新进度条UI
    this.__progressUI.emit(ProgressUIEvent.Update, percent);

    // 创建下载统计信息元素
    const statsElement = document.createElement('div');
    statsElement.style.cssText = 'padding: 8px; font-size: 12px; line-height: 1.5;';
    statsElement.innerHTML = `
      <div>总大小: ${fromBytes(total)}</div>
      <div>下载大小: ${fromBytes(downloaded)}</div>
      <div>下载速度: ${fromBytes(speed)}/s</div>
    `;

    // 更新工具提示内容
    this.__tooltip.update({
      type: 'element',
      content: statsElement
    });
  }

  /**
   * 显示下载错误状态
   * @param message - 错误消息
   */
  showErrorState(message: string): void {
    this.__tooltip.update({
      type: 'text',
      content: `下载失败: ${message}`
    });
    // 错误状态不应将进度设置为100%
    // 保持当前进度以显示失败位置
  }

  /**
   * 重置进度UI到初始状态
   */
  resetProgress(): void {
    this.__progressUI.emit(ProgressUIEvent.Update, 0);
  }

  /**
   * 获取进度UI元素
   * @returns 进度UI元素
   */
  getElement(): HTMLElement {
    return this.__progressUI.getElement();
  }
}